package graphdao

import (
	"power/core/dao/table"
	"power/core/service/common"
	"power/core/service/graph"

	"strconv"

	"github.com/RocksonZeta/wrap/redised"
	"github.com/RocksonZeta/wrap/utils/sqlutil"
	"github.com/RocksonZeta/wrap/utils/sutil"
	"github.com/RocksonZeta/wrap/utils/timeutil"
)

const tableGraphElementProto = "GraphElementProto"

type GraphElementProtos struct {
	*redised.RedisedMysql
}

func (s GraphElementProtos) redisKey(id int) string {
	return tableGraphElementProto + "/" + strconv.Itoa(id)
}
func (s GraphElementProtos) redisKeyAll() string {
	return tableGraphElementProto + "/all"
}

func (s GraphElementProtos) ClearCache(old table.GraphElementProto) {
	s.Redis.Del(s.redisKey(old.Id))
	s.Redis.Del(s.KVFn(tableGraphElementProto, sutil.M{"uid": old.Uid}))
	s.Redis.Del(s.KVFn(tableGraphElementProto, sutil.M{"classId": old.ClassId}))
}

type GraphElementProtosQueryParam struct {
	common.Page
	Name string
}

//Query 根据条件查询
func (s GraphElementProtos) Query(param GraphElementProtosQueryParam) ([]table.GraphElementProto, int64) {
	wsql := " from GraphElementProto where 1=1"
	if param.Name != "" {
		param.Name = "%" + param.Name + "%"
		wsql += " and name like :Name"
	}
	ssql := "select *" + wsql + " order by ct desc" + param.Limit()
	csql := "select count(*)" + wsql
	var r []table.GraphElementProto
	s.Mysql.Select(&r, ssql, param)
	return r, s.Mysql.SelectInt(csql, param)
}

func (s GraphElementProtos) Get(id int) table.GraphElementProto {
	var r table.GraphElementProto
	s.RedisedMysql.Get(&r, tableGraphElementProto, "Id", id)
	return r
}
func (s GraphElementProtos) Get_(id int) graph.GraphElementProto {
	var r graph.GraphElementProto
	e := s.Get(id)
	r.GraphElementProto = e
	r.Props = graph.UnmarshalProps(e.Props)
	return r
}
func (s GraphElementProtos) ListByUid(uid int) []table.GraphElementProto {
	var r []table.GraphElementProto
	s.RedisedMysql.ListByKvs(&r, tableGraphElementProto, "Id", sutil.M{"uid": uid})
	return r
}
func (s GraphElementProtos) ListByClassId(classId int) []table.GraphElementProto {
	var r []table.GraphElementProto
	s.RedisedMysql.ListByKvs(&r, tableGraphElementProto, "Id", sutil.M{"classId": classId})
	return r
}
func (s GraphElementProtos) ListByClassId_(classId int) []graph.GraphElementProto {
	return s.ParseList(s.ListByClassId(classId))
}

func (s GraphElementProtos) List(ids []int) []table.GraphElementProto {
	var r []table.GraphElementProto
	s.RedisedMysql.List(&r, tableGraphElementProto, "Id", ids)
	return r
}

func (s GraphElementProtos) ListAsMap_(ids []int) map[int]graph.GraphElementProto {
	l := s.List(ids)
	r := make(map[int]graph.GraphElementProto, len(l))
	for _, v := range l {
		var p graph.GraphElementProto
		p.GraphElementProto = v
		p.Props = graph.UnmarshalProps(v.Props)
		r[v.Id] = p
	}
	return r
}
func (s GraphElementProtos) ListByClassIds(classIds []int) []table.GraphElementProto {
	var r []table.GraphElementProto
	s.RedisedMysql.ListBySql(&r, s.redisKeyAll(), "select * from "+tableGraphElementProto+" where classId in ("+sqlutil.JoinInts(classIds)+") order by no,ct")
	return r
}
func (s GraphElementProtos) ListByClassIds_(classIds []int) []graph.GraphElementProto {
	l := s.ListByClassIds(classIds)
	r := make([]graph.GraphElementProto, len(l))
	for i, v := range l {
		var p graph.GraphElementProto
		p.GraphElementProto = v
		p.Props = graph.UnmarshalProps(v.Props)
		r[i] = p
	}
	return r
}

// func (s GraphElementProtos) ListAll_() []graph.GraphElementProto {
// 	l := s.ListAll()
// 	r := make([]graph.GraphElementProto, len(l))
// 	for i, v := range l {
// 		var p graph.GraphElementProto
// 		p.GraphElementProto = v
// 		p.Props = graph.UnmarshalProps(v.Props)
// 		r[i] = p
// 	}
// 	return r
// }

func (s GraphElementProtos) ParseList(l []table.GraphElementProto) []graph.GraphElementProto {
	r := make([]graph.GraphElementProto, len(l))

	for i, v := range l {
		r[i].GraphElementProto = v
		r[i].Props = graph.UnmarshalProps(v.Props)
	}
	return r
}
func (s GraphElementProtos) List2Map(l []table.GraphElementProto) map[int]graph.GraphElementProto {
	r := make(map[int]graph.GraphElementProto, len(l))
	for _, v := range l {
		var p graph.GraphElementProto
		p.GraphElementProto = v
		p.Props = graph.UnmarshalProps(v.Props)
		r[v.Id] = p
	}
	return r
}
func (s GraphElementProtos) CountByClassIdUid(classId, uid int) int {
	r := s.Mysql.SelectInt("select count(*) from "+tableGraphElementProto+" where classId=? and uid=?", classId, uid)
	return int(r)
}

type GraphElementProtosAddParam struct {
	Id int
	//ClassId field:classId int; normal index:gecid; fk:gecid ref:GraphElementProtoClass.id
	ClassId int
	//Props field:props json;
	Props string
	//Name field:name varchar(200);
	Name string
	//No field:no int;
	Type int
	//Icon field:icon varchar(200);
	Icon string
	//Uid field:uid int; normal index:gepuid; fk:gepuid ref:User.id
	Uid int
}

func (s GraphElementProtos) Add(param GraphElementProtosAddParam) table.GraphElementProto {
	var t table.GraphElementProto
	sutil.Copy(param, &t)
	t.Ct = timeutil.Now()
	t.No = s.CountByClassIdUid(param.ClassId, param.Uid) + 1
	s.Mysql.AddTable(t)
	s.Mysql.Insert(&t)
	s.ClearCache(t)
	return t
}

type GraphElementProtosUpdateParam struct {
	Id   int
	Name string
}

func (s GraphElementProtos) Update(param GraphElementProtosUpdateParam) {
	s.Mysql.Patch(tableGraphElementProto, "Id", param)
	s.ClearCache(s.Get(param.Id))

}

func (s GraphElementProtos) UpdateProps(id int, props string) {
	s.Mysql.Patch(tableGraphElementProto, "id", sutil.Kv2Map("id", id, "props", props))
	s.ClearCache(s.Get(id))
}
func (s GraphElementProtos) UpdateData(id int, data string) {
	s.Mysql.Patch(tableGraphElementProto, "id", sutil.Kv2Map("id", id, "data", data))
	s.ClearCache(s.Get(id))
}

func (s GraphElementProtos) Delete(id int) {
	old := s.Get(id)
	s.Mysql.Delete(tableGraphElementProto, "Id", id)
	s.ClearCache(old)
}
